from random import randint, shuffle
import tkinter
from tkinter.ttk import Combobox
from itertools import product
from tkinter.messagebox import showinfo
from board import get_board, distance_quart, distance_max
from graphics import fit_to_board


def draw():
    for x, y in product(range(WIDTH.get()), range(HEIGHT.get())):
        coordinates = canvas.coords(f"{x}/{y}")
        flag = True
        for cx, cy in zip(coordinates[::2], coordinates[1::2]):
            if 0 < cx < 800 and 0 < cy < 800:
                continue
            else:
                flag = False
                break
        if flag:
            canvas.itemconfig(f"{x}/{y}", fill=f"#{BOARD[y][x]}", outline=f"#000")
        else:
            canvas.itemconfig(f"{x}/{y}", fill=f"#{BOARD[y][x]}", outline=f"#000")


def handler(event: tkinter.Event):
    if not shv.get():
        shv.set("Количество ходов")


def change(event: tkinter.Event, direction: int):
    tag = canvas.gettags("current")[0]
    x0, y0 = map(int, tag.split("/"))
    next_color(x0, y0, direction)
    draw()
    if check(): showinfo(message="Собрано!")


def shuffle_plane():
    for _ in range(int(shv.get())):
        next_color(
            randint(0, WIDTH.get() - 1),
            randint(0, HEIGHT.get() - 1),
            1
        )


def check() -> bool:
    ch = BOARD[0][0]
    for x, y in product(range(WIDTH.get()), range(HEIGHT.get())):
        new = BOARD[y][x]
        if ch != new:
            return False
    return True


def next_color(x0: int, y0: int, d: int):
    pass
    c = COLORS
    cc = COLOR_COUNT.get()
    h = HEIGHT.get()
    w = WIDTH.get()
    for x, y in product(range(w), range(h)):
        if distance_quart(SHAPE.get(), x, y, x0, y0) <= 1:
            BOARD[y][x] = c[(c.index(BOARD[y][x]) + d) % cc]  # Сосед


def command(t: str):
    global BOARD
    match t:
        case "solve":
            shuffle(COLORS)
            BOARD = get_board(COLORS[0], WIDTH.get(), HEIGHT.get())
            draw()
        case "play":
            main_menu.place_forget()
            game.place(x=0, y=0, width=800, height=800)
            command("solve")
            w, h = WIDTH.get(), HEIGHT.get()
            size = 100
            canvas.delete("all")
            for w0, h0 in product(range(w), range(h)):
                canvas.create_polygon(
                    fit_to_board(SHAPE.get(), w0, h0, size / (2 if SHAPE.get() == 6 else 1)),
                    fill=f"#{BOARD[h0][w0]}", tags=f"{w0}/{h0}", outline="#000"
                )

                canvas.tag_bind(f"{w0}/{h0}", "<Button-1>", lambda e: change(e, 1))
                canvas.tag_bind(f"{w0}/{h0}", "<Button-3>", lambda e: change(e, -1))

            canvas.configure(scrollregion=canvas.bbox("all"))

        case "shuffle":
            shuffle(COLORS)
            if shv.get().isnumeric():
                shuffle_plane()
                draw()
        case "settings":
            main_menu.place_forget()
            settings.place(x=0, y=0, width=800, height=800)
        case "back":
            settings.place_forget()
            rules.place_forget()
            game.place_forget()
            main_menu.place(x=0, y=0, width=800, height=800)
        case "rules":
            main_menu.place_forget()
            rules.place(x=0, y=0, width=800, height=800)


if __name__ == "__main__":
    COLORS = list(map("".join, product(*(3 * ["0123456789ABCDEF"]))))
    BOARD = get_board()
    window = tkinter.Tk()
    window.geometry(f"800x800+{window.winfo_screenwidth() // 2 - 400}+{window.winfo_screenheight() // 2 - 400}")
    window.resizable(False, False)
    window.title("RGBShapes")

    main_menu = tkinter.Frame()
    info_button = tkinter.Button(main_menu)
    tkinter.Button(main_menu, text="Играть", command=lambda: command("play")) \
        .place(x=0, y=0, width=800, height=200)
    tkinter.Button(main_menu, text="Настройки", command=lambda: command("settings")) \
        .place(x=0, y=200, width=800, height=200)
    tkinter.Button(main_menu, text="Правила", command=lambda: command("rules")) \
        .place(x=0, y=400, width=800, height=200)
    tkinter.Button(main_menu, text="Выход", command=exit) \
        .place(x=0, y=600, width=800, height=200)

    # Settings

    settings = tkinter.Frame()

    WIDTH = tkinter.IntVar(value=10)
    HEIGHT = tkinter.IntVar(value=10)
    COLOR_COUNT = tkinter.IntVar(value=3)
    SHAPE = tkinter.IntVar(value=6)

    Combobox(settings, textvariable=SHAPE, values=(3, 4, 6), justify="center", state="readonly") \
        .place(x=400, y=0, width=400, height=160)
    tkinter.Label(settings, text="Количество углов правильной фигуры", justify="center") \
        .place(x=0, y=0, width=400, height=160)

    tkinter.Entry(settings, textvariable=WIDTH, justify="center") \
        .place(x=400, y=160, width=400, height=160)
    tkinter.Label(settings, text="Ширина", justify="center") \
        .place(x=0, y=160, width=400, height=160)

    tkinter.Entry(settings, textvariable=HEIGHT, justify="center") \
        .place(x=400, y=320, width=400, height=160)
    tkinter.Label(settings, text="Длина", justify="center") \
        .place(x=0, y=320, width=400, height=160)

    tkinter.Entry(settings, textvariable=COLOR_COUNT, justify="center") \
        .place(x=400, y=480, width=400, height=160)
    tkinter.Label(settings, text="Количество цветов", justify="center") \
        .place(x=0, y=480, width=400, height=160)

    tkinter.Button(settings, text="Назад", command=lambda: command("back")) \
        .place(x=0, y=640, width=800, height=160)

    # Game

    shv = tkinter.StringVar()
    game = tkinter.Frame()

    canvas = tkinter.Canvas(game)
    frame = tkinter.Frame(canvas)
    x_scroll = tkinter.Scrollbar(game, orient="horizontal", command=canvas.xview)
    y_scroll = tkinter.Scrollbar(game, orient="vertical", command=canvas.yview)

    canvas.configure(xscrollcommand=x_scroll.set)
    canvas.configure(yscrollcommand=y_scroll.set)

    shuffle_box = tkinter.Frame(game)
    tkinter.Button(shuffle_box, text="Размешать", command=lambda: command("shuffle")). \
        place(x=0, y=0, width=800 / 2, height=20)
    shuffle_entry = tkinter.Entry(shuffle_box, textvariable=shv, justify="center")
    shuffle_entry.place(x=800 / 2, y=0, width=800 / 2, height=20)
    shuffle_entry.bind("<Leave>", handler)
    shuffle_entry.bind("<Enter>", handler)
    del shuffle_entry
    canvas \
        .place(x=20, y=0, width=780, height=720)
    x_scroll. \
        place(x=20, y=720, width=780, height=20)
    y_scroll. \
        place(x=0, y=0, width=20, height=720)
    shuffle_box \
        .place(x=0, y=740, width=800, height=20)
    tkinter.Button(game, text="Собрать", command=lambda: command("solve")) \
        .place(x=0, y=760, width=800, height=20)
    tkinter.Button(game, text="Назад", command=lambda: command("back")) \
        .place(x=0, y=780, width=800, height=20)

    # Rules

    rules = tkinter.Frame()
    tkinter.Label(rules, text="Щёлкай по ячейкам, чтоб покрасить их всех в один цвет") \
        .place(x=0, y=0, width=800, height=780)
    tkinter.Button(rules, text="Назад", command=lambda: command("back")) \
        .place(x=0, y=780, width=800, height=20)

    command("back")

    window.mainloop()
